package com.barneyx.mshinfoplatform.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.json.JSONParser;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.barneyx.mshinfoplatform.common.ExResult;
import com.barneyx.mshinfoplatform.entity.common.DefaultSettingConfig;
import com.barneyx.mshinfoplatform.entity.enums.EEventType;
import com.barneyx.mshinfoplatform.entity.enums.EInfoState;
import com.barneyx.mshinfoplatform.entity.enums.EPlatformType;
import com.barneyx.mshinfoplatform.entity.info.*;
import com.barneyx.mshinfoplatform.entity.user.UserEntity;
import com.barneyx.mshinfoplatform.exception.InfoException;
import com.barneyx.mshinfoplatform.exception.MshException;
import com.barneyx.mshinfoplatform.exception.UserException;
import com.barneyx.mshinfoplatform.service.area.IAreaEntityService;
import com.barneyx.mshinfoplatform.service.info.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import static com.barneyx.mshinfoplatform.common.ExResult.ResponseCode.*;
import static com.barneyx.mshinfoplatform.entity.info.InfoSettingEntity.ISettingCode.*;

@Component
@Slf4j
public class InfoUtil {
    @Resource
    private IInfoEntityService infoService;

    @Resource
    private IInfoCateEntityService infoCateService;

    @Resource
    private IInfoHistoryEntityService infoHistoryService;

    @Resource
    private UserUtil userUtil;


    @Resource
    private AreaUtil areaUtil;

    @Resource
    private EventUtil eventUtil;

    @Component
    public class Info {

        @Resource
        private InfoUtil.Setting infoSettingUtil;

        /**
         * 设置指定信息状态
         *
         * @param infoId
         * @param state
         * @return
         */
        public boolean InfoSH(String infoId, EInfoState state) {
            InfoEntity info = infoService.getById(infoId);
            info.setState(state);

            return infoService.update(new LambdaUpdateWrapper<InfoEntity>()
                    .eq(InfoEntity::getInfoId, info.getInfoId())
                    .set(InfoEntity::getState, state));
        }

        public boolean InfoSH(String infoId, EInfoState state, String errorMsg) {
            if (StrUtil.isBlank(errorMsg)) errorMsg = "您发布的信息有误,请检查内容后重新修改!";
            InfoEntity info = infoService.getById(infoId);
            info.setState(state);
            return infoService.update(new LambdaUpdateWrapper<InfoEntity>()
                    .eq(InfoEntity::getInfoId, info.getInfoId())
                    .set(InfoEntity::getState, state)
                    .set(InfoEntity::getErrorMsg, errorMsg)
            );
        }


        public IInfoEntityService getInfoService() {
            return infoService;
        }

        public AreaUtil getAreaUtil() {
            return areaUtil;
        }


        public Page<InfoEntity> getPage(long current, long size, LambdaQueryWrapper<InfoEntity> lambdaQueryWrapper) throws MshException {
            lambdaQueryWrapper
                    .eq(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                    .eq(InfoEntity::getState, EInfoState.PASS)
                    .orderByDesc(InfoEntity::getIsTop)
                    .orderByDesc(InfoEntity::getCreateAt);
            Page<InfoEntity> page = infoService.page(new Page<>(current, size), lambdaQueryWrapper);

            //分页清空正文信息:
            //目的:节约流量,增加传输速度
            if (page != null && !page.getRecords().isEmpty()) {
                page.getRecords().forEach(info -> {
                    info.setRemark(null);
                });
            }
            return page;
        }

        public Page<InfoEntity> getPage2(long current, long size, LambdaQueryWrapper<InfoEntity> lambdaQueryWrapper) throws MshException {
            lambdaQueryWrapper
                    .eq(InfoEntity::getAreaId, areaUtil.getCurrentAreaId())
                    .orderByDesc(InfoEntity::getIsTop)
                    .orderByDesc(InfoEntity::getCreateAt);
            Page<InfoEntity> page = infoService.page(new Page<>(current, size), lambdaQueryWrapper);

            //分页清空正文信息:
            //目的:节约流量,增加传输速度
            if (page != null && !page.getRecords().isEmpty()) {
                page.getRecords().forEach(info -> {
                    info.setRemark(null);
                });
            }
            return page;
        }

        /**
         * 创建信息
         *
         * @param info
         * @return
         * @throws InfoException
         * @throws UserException
         */
        public boolean createInfo(InfoEntity info) throws MshException {
            if (!StrUtil.isAllNotBlank(
                    info.getRemark(),
                    info.getInfoCateId(),
                    info.getLtdContact(),
                    info.getLtdPhone()
            )) throw new InfoException(FIELD_ERROR);
            if (StrUtil.length(info.getInfoDescription()) < 10)
                info.setInfoDescription(StrUtil.subPreGbk(HtmlUtil.cleanHtmlTag(info.getRemark()), 100, "..."));
            info.setAreaId(areaUtil.getCurrentAreaId());
            info.setUserId(userUtil.getCurrentLoginMastUserInfo().getUserId());
            info.setCateName(infoCateService.getById(info.getInfoCateId()).getInfoCateName());
            info.setInfoPostName(userUtil.getCurrentLoginMastUserInfo().getNickName());
            info.setInfoPostVia(userUtil.getCurrentLoginMastUserInfo().getVia());
            info.setUserPlatformId(userUtil.getCurrentLoginMastUserInfo().getUserPlatformId());
            info.setPlatformType(userUtil.getCurrentLoginUserInfo().getPlatformIdentification());
            boolean save = infoService.save(info);
            if (!save) throw new InfoException(INFO_NOT_CREATE_ERROR);
            eventUtil.SendInfoAuditEvent(EEventType.EVENT_INFO_CREATE_AUDIT, info);
            return save;
        }

        /**
         * 创建信息检查当前用户是否满足发布条件
         *
         * @param info
         * @return
         * @throws InfoException
         * @throws UserException
         */
        public boolean createInfoAndCheck(InfoEntity info) throws MshException {
            infoSettingUtil.CheckUserIsPost(info.getUserId());
            if (!StrUtil.isAllNotBlank(
                    info.getRemark(),
                    info.getInfoCateId(),
                    info.getLtdContact(),
                    info.getLtdPhone()
            )) throw new InfoException(FIELD_ERROR);
            info.setInfoDescription(StrUtil.subPreGbk(HtmlUtil.cleanHtmlTag(info.getRemark()), 70, "..."));
            info.setAreaId(areaUtil.getCurrentAreaId());
            info.setUserId(userUtil.getCurrentLoginMastUserInfo().getUserId());
            info.setCateName(infoCateService.getById(info.getInfoCateId()).getInfoCateName());
            info.setInfoPostName(userUtil.getCurrentLoginMastUserInfo().getNickName());
            info.setInfoPostVia(userUtil.getCurrentLoginMastUserInfo().getVia());
            info.setUserPlatformId(userUtil.getCurrentLoginMastUserInfo().getUserPlatformId());
            info.setPlatformType(userUtil.getCurrentLoginUserInfo().getPlatformIdentification());
            boolean save = infoService.save(info);
            if (!save) throw new InfoException(INFO_NOT_CREATE_ERROR);
            return true;
        }

        /**
         * 更新信息
         *
         * @param info
         * @return
         * @throws InfoException
         */
        @Transactional
        public boolean updateInfoBaseInfo(InfoEntity info) throws InfoException {
            if (!StrUtil.isAllNotBlank(
                    info.getRemark(),
                    info.getInfoCateId(),
                    info.getLtdContact(),
                    info.getUserId(),
                    info.getInfoId(),
                    info.getUserPlatformId()
            )) throw new InfoException(FIELD_ERROR);
//            if(StrUtil.length(info.getInfoDescription())<=20)
            info.setInfoDescription(StrUtil.subPreGbk(StrUtil.cleanBlank(HtmlUtil.cleanHtmlTag(info.getRemark())), 200, "..."));
            //修改，则将信息状态改变审核状态
            info.setState(EInfoState.AUDIT);
            InfoEntity info_entity = infoService.getById(info.getInfoId());
            if (info_entity == null) throw new InfoException(INFO_NOT_FOUND_ERROR);
            InfoHistoryEntity historyInfo = new InfoHistoryEntity();
            BeanUtil.copyProperties(info_entity, historyInfo);
            boolean save = infoHistoryService.save(historyInfo);
            boolean update = infoService.update(new LambdaUpdateWrapper<InfoEntity>()
                    .eq(InfoEntity::getInfoId, info.getInfoId())
                    .set(InfoEntity::getRemark, info.getRemark())
                    .set(InfoEntity::getLtdContact, info.getLtdContact())
                    .set(InfoEntity::getLtdPhone, info.getLtdPhone())
                    .set(InfoEntity::getInfoDescription, info.getInfoDescription())
                    .set(InfoEntity::getInfoTags, JSONObject.toJSONString(info.getInfoTags()))
                    .set(InfoEntity::getAlbums, JSONObject.toJSONString(info.getAlbums()))
            );
            if (save && update) {
                eventUtil.SendInfoAuditEvent(EEventType.EVENT_INFO_UPDATE_AUDIT, info);
            }
            return save && update;
        }


        //获取当前用户的信息
        public Page<InfoEntity> getUserPlatformIdByInfos(long current, long size, String userplatformId) throws UserException, InfoException {
            if (StrUtil.isBlank(userplatformId)) throw new InfoException(INFO_ID_NOT_NULL);
            return infoService.page(new Page<>(current, size), new LambdaQueryWrapper<InfoEntity>()
                    .in(InfoEntity::getUserPlatformId, userUtil.getUserPlatformIds(userplatformId))
                    .orderByDesc(InfoEntity::getCreateAt));
        }


        /**
         * 更新信息点击量
         *
         * @param infoId
         * @return
         */
        public boolean updateInfoClickCount(String infoId) {
            InfoEntity info = infoService.getById(infoId);
            Long clickCount = info.getClickCount();
            clickCount += 1;
            return infoService.update(new LambdaUpdateWrapper<InfoEntity>()
                    .eq(InfoEntity::getInfoId, infoId)
                    .set(InfoEntity::getClickCount, clickCount));
        }

        /**
         * 更新信息阅读量
         *
         * @param infoId
         * @return
         */
        public boolean updateInfoReadCount(String infoId) {
            InfoEntity info = infoService.getById(infoId);
            Long readCount = info.getReadCount();
            readCount += 1;
            return infoService.update(new LambdaUpdateWrapper<InfoEntity>()
                    .eq(InfoEntity::getInfoId, infoId)
                    .set(InfoEntity::getReadCount, readCount));
        }


    }

    @Component
    public class Cate {

        public IInfoCateEntityService getCateService() {
            return infoCateService;
        }


        public boolean deleteById(String cateId) {
            return infoCateService.removeById(cateId);
        }

        /**
         * 获取指定信息分类的子分类
         *
         * @param cateId
         * @return
         */
        public List<InfoCateEntity> getInfoCateChildList(String cateId) {
            InfoCateEntity parent_cate_info = infoCateService.getById(cateId);
            if (parent_cate_info != null) {
                return infoCateService.list(new LambdaQueryWrapper<InfoCateEntity>()
                        .eq(InfoCateEntity::getInfoCateParentId, cateId));
            }
            return null;
        }

        /**
         * 修改分类的排序
         *
         * @param cateid
         * @param sort
         * @return
         */
        public boolean updateCateSort(String cateid, int sort) {
            return infoCateService.update(new LambdaUpdateWrapper<InfoCateEntity>()
                    .eq(InfoCateEntity::getInfoCateId, cateid)
                    .set(InfoCateEntity::getInfoCateSort, sort));
        }

        /**
         * 更新显示状态
         *
         * @param cateid
         * @param filedName
         * @param state
         * @return
         */
        public boolean ChangeCateShowType(String cateid, String filedName, boolean state) {
            InfoCateEntity cate = infoCateService.getById(cateid);
            boolean update = false;
            switch (filedName.trim().toUpperCase(Locale.ROOT)) {
                case "HOME":
                    update = infoCateService.update(new LambdaUpdateWrapper<InfoCateEntity>()
                            .eq(InfoCateEntity::getInfoCateId, cateid)
                            .set(InfoCateEntity::isHomeShow, state));
                    break;
                case "POST":
                    update = infoCateService.update(new LambdaUpdateWrapper<InfoCateEntity>()
                            .eq(InfoCateEntity::getInfoCateId, cateid)
                            .set(InfoCateEntity::isPostHomeShow, state));
                    break;
                case "GLOBAL":
                    update = infoCateService.update(new LambdaUpdateWrapper<InfoCateEntity>()
                            .eq(InfoCateEntity::getInfoCateId, cateid)
                            .set(InfoCateEntity::getGlobalInfoShow, state));
                    break;
                default:
                    break;
            }

            return update;
        }

        /**
         * 获取指定分类下面的子分类下的所有子分类的id列表
         *
         * @param cateId
         * @return
         */
        public List<String> getInfoCateChildIds(String cateId) {
            List<InfoCateEntity> infoCateChildList = this.getInfoCateChildList(cateId);
            if (infoCateChildList.isEmpty()) return null;
            return infoCateChildList.stream().map(InfoCateEntity::getInfoCateId).collect(Collectors.toList());
        }

        /**
         * 创建分类
         *
         * @param infoCate
         * @return
         */
        public boolean createCate(InfoCateEntity infoCate) throws MshException {
            if (StrUtil.isAllBlank(infoCate.getInfoCateName())) throw new MshException(INFO_CATE_FIELD_ERROR);
            return infoCateService.save(infoCate);
        }

        /**
         * 修改分类
         *
         * @param infoCate
         * @return
         * @throws MshException
         */
        public boolean updateCate(InfoCateEntity infoCate) throws MshException {
            if (StrUtil.isAllBlank(
                    infoCate.getInfoCateId(),
                    infoCate.getInfoCateName()
            )) throw new MshException(INFO_CATE_FIELD_ERROR);
            return infoCateService.update(new LambdaUpdateWrapper<InfoCateEntity>()
                    .eq(InfoCateEntity::getInfoCateId, infoCate.getInfoCateId())
                    .set(InfoCateEntity::getInfoCateName, infoCate.getInfoCateName())
                    .set(InfoCateEntity::getInfoCateIcon, infoCate.getInfoCateIcon())
                    .set(InfoCateEntity::getInfoCatePath, infoCate.getInfoCatePath())
                    .set(InfoCateEntity::getInfoCateSort, infoCate.getInfoCateSort())
                    .set(InfoCateEntity::getGlobalInfoShow, infoCate.getGlobalInfoShow())
                    .set(InfoCateEntity::isHomeShow, infoCate.isHomeShow())
                    .set(InfoCateEntity::isPostHomeShow, infoCate.isPostHomeShow())
            );
        }


        @Component
        public class Tag {
            @Resource
            public IInfoCateTagsEntityService cateTagService;


            public boolean changeTagName(String tagId, String tagName, String tagColor) {
                return cateTagService.update(new LambdaUpdateWrapper<InfoCateTagsEntity>()
                        .eq(InfoCateTagsEntity::getTagId, tagId)
                        .set(InfoCateTagsEntity::getTagName, tagName)
                        .set(InfoCateTagsEntity::getTagColor, tagColor));
            }


            public boolean deleteTagById(String tagId) {
                return cateTagService.removeById(tagId);
            }

            public boolean createTag(InfoCateTagsEntity tag) {
                return cateTagService.save(tag);
            }

            public List<InfoCateTagsEntity> getList(String cateId) {
                return cateTagService.list(new LambdaQueryWrapper<InfoCateTagsEntity>()
                        .eq(InfoCateTagsEntity::getCateId, cateId));
            }


        }

    }


    @Component
    public class Setting {
        @Resource
        private IInfoSettingEntityService infoSettingService;


        /**
         * 获取当前区域的广告列表
         *
         * @return
         * @throws MshException
         */
        public InfoSettingEntity getAdvList() throws MshException {
            String currentAreaId = areaUtil.getCurrentAreaId();
            return infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                    .eq(InfoSettingEntity::getAreaId, currentAreaId)
                    .eq(InfoSettingEntity::getInfoSettingCode, InfoSettingEntity.ISettingCode.ADV_SETTINGS));
        }


        /**
         * 获取区域指定设置参数
         *
         * @param key
         * @return
         * @throws MshException
         */
        public InfoSettingEntity getInfoSetting(String key) throws MshException {
            String currentAreaId = areaUtil.getCurrentAreaId();
            return infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                    .eq(InfoSettingEntity::getAreaId, currentAreaId)
                    .eq(InfoSettingEntity::getInfoSettingCode, key.trim()));
        }

        public InfoSettingEntity getInfoSettingNoArea(String key) throws MshException {
            return infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                    .eq(InfoSettingEntity::getInfoSettingCode, key.trim()));
        }


        /**
         * 检查当前用户是否满足系统设定的发布条件
         *
         * @param userId
         * @return
         */
        @SneakyThrows
        public boolean CheckUserIsPost(String userId) {
            InfoSettingEntity enablePost = infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                    .eq(InfoSettingEntity::getInfoSettingCode, USER_POST_ENABLE));
            //如果系统未开启发布条件则说明没有限制，用户直接发布
            if (enablePost.getInfoSettingValue().equalsIgnoreCase("FALSE")) return true;
            else {
                InfoSettingEntity feriodType = infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                        .eq(InfoSettingEntity::getInfoSettingCode, USER_POST_PERIOD));
                InfoSettingEntity feriodTypeVal = infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                        .eq(InfoSettingEntity::getInfoSettingCode, USER_POST_PERIOD_VAL));

                switch (feriodType.getInfoSettingValue().toUpperCase(Locale.ROOT)) {
                    case "DAY": {
                        long count = infoService.count(new LambdaQueryWrapper<InfoEntity>()
                                .eq(InfoEntity::getUserId, userId)
                                .between(InfoEntity::getCreateAt, DateUtil.beginOfDay(new Date()), DateUtil.endOfDay(new Date()))
                        );
                        if (count > Long.parseLong(feriodTypeVal.getInfoSettingValue()))
                            throw new InfoException("发布失败，慢生活信息平台限制，用户1天内发布次数不能超过" + feriodTypeVal.getInfoSettingValue() + "次");
                        return true;
                    }

                    case "WEEK": {
                        long count = infoService.count(new LambdaQueryWrapper<InfoEntity>()
                                .eq(InfoEntity::getUserId, userId)
                                .between(InfoEntity::getCreateAt, DateUtil.beginOfWeek(new Date()), DateUtil.endOfWeek(new Date()))
                        );
                        if (count > Long.parseLong(feriodTypeVal.getInfoSettingValue()))
                            throw new InfoException("发布失败，慢生活信息平台限制，用户1周内发布次数不能超过" + feriodTypeVal.getInfoSettingValue() + "次");

                        return true;
                    }
                    case "MONTH": {
                        long count = infoService.count(new LambdaQueryWrapper<InfoEntity>()
                                .eq(InfoEntity::getUserId, userId)
                                .between(InfoEntity::getCreateAt, Util.currentMonthStart(), Util.currentMonthEnd())
                        );
                        if (count > Long.parseLong(feriodTypeVal.getInfoSettingValue()))
                            throw new InfoException("发布失败，慢生活信息平台限制，用户1月内发布次数不能超过" + feriodTypeVal.getInfoSettingValue() + "次");

                        return true;
                    }

                    case "YEAR": {
                        Util.getYearFirst(2023);
                        long count = infoService.count(new LambdaQueryWrapper<InfoEntity>()
                                .eq(InfoEntity::getUserId, userId)
                                .between(InfoEntity::getCreateAt, Util.getYearFirst(Util.getCurrentYear()), Util.getYearLast(Util.getCurrentYear()))
                        );
                        if (count > Long.parseLong(feriodTypeVal.getInfoSettingValue()))
                            throw new InfoException("发布失败，慢生活信息平台限制，用户1年内发布次数不能超过" + feriodTypeVal.getInfoSettingValue() + "次");
                        return true;
                    }

                }


                return false;
            }
        }

        /**
         * 检查当前系统对信息的审核状态，如果是不开启审核则直接通过，如果是需要审核
         *
         * @param info
         */
        public void CheckInfoState(InfoEntity info) {
            InfoSettingEntity enableInfoAudit = infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                    .eq(InfoSettingEntity::getInfoSettingCode, INFO_STATE_AUDIT_ENABLE));
            if (enableInfoAudit.getInfoSettingValue().equalsIgnoreCase("TRUE"))
                info.setState(EInfoState.AUDIT);
            else
                info.setState(EInfoState.PASS);
        }

        //获取指定地区的管理员是否开启邮件通知并返回邮箱地址
        public String getAreaManageUserEmailByInfoId(String areaId) {
            if (areaId == null) return null;
            InfoSettingEntity PostEmailEnable = infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                    .eq(InfoSettingEntity::getInfoSettingCode, AREA_EMAIL_NOTIFY_ENABLE).eq(InfoSettingEntity::getAreaId, areaId));
            if (PostEmailEnable.getInfoSettingValue().equalsIgnoreCase("true")) {
                InfoSettingEntity PostEmailAddr = infoSettingService.getOne(new LambdaQueryWrapper<InfoSettingEntity>()
                        .eq(InfoSettingEntity::getInfoSettingCode, AREA_EMAIL_NOTIFY_ADDR).eq(InfoSettingEntity::getAreaId, areaId));
                String email_addr = PostEmailAddr.getInfoSettingValue();
                if (email_addr != null && Util.isValidEmail(email_addr)) return email_addr;
                else return null;
            }
            return null;
        }
    }
}
